package sis.searchtest;/*
 * @auther 顶风少年
 * @mail dfsn19970313@foxmail.com
 * @date 2019-08-01 11:11
 * @notify
 * @version 1.0
 */

import com.sun.org.apache.regexp.internal.RE;
import junit.framework.TestCase;
import sis.search.ResultsListener;
import sis.search.Search;
import sis.search.Server;
import sis.util.LineWriter;
import sis.util.TestUtil;

import java.net.URL;
import java.util.List;

//该测试保证 添加搜索和搜索异步进行
//服务器一直在接收搜索.
//客户端循环添加搜索
public class ServerTest extends TestCase {
    //当前搜索次数
    private int numberOfResults = 0;
    //搜索服务器
    private Server server;
    //超时时间
    private static final long TIMEOUT = 300L;
    //搜索路径
    private static final String[] URLS = {
            SearchTest.URL, SearchTest.URL, SearchTest.URL
    };

    protected void setUp() throws Exception {
        //创建搜索文件
        TestUtil.delete(SearchTest.FILE);
        LineWriter.write(SearchTest.FILE, SearchTest.TEST_HTML);

        //监听器
        ResultsListener listener = new ResultsListener() {
            //增加搜索次数
            public void executed(Search search) {
                numberOfResults++;
            }
        };
        //创建服务器
        server = new Server(listener);
    }

    //删除搜索文件
    protected void tearDown() throws Exception {
        //server线程还存在
        assertTrue(server.isAlive());
        //中断server线程
        server.shutDown();
        server.join(3000);
        assertFalse(server.isAlive());
        TestUtil.delete(SearchTest.FILE);
    }

    //测试搜索
    public void testSearch() throws Exception {
        //开始搜索时间
        long start = System.currentTimeMillis();
        //添加搜索
        executeSearches();
        //添加搜索结束时间
        long elapsed = System.currentTimeMillis() - start;
        //断言添加三次搜索时间小于 20
        assertTrue(elapsed < 20);
        //测试是否超时
        waitForResults();
    }


    public void testException() throws Exception {
        final String errorMessage = "problem";
        Search faultySearch = new Search(URLS[0], "") {
            public void execute() {
                throw new RuntimeException(errorMessage);
            }
        };
        server.add(faultySearch);
        waitForResults(1);
        List<String> log = server.getLog();
        assertTrue(log.get(0).indexOf(errorMessage)!=-1);
    }

    private void waitForResults(){
        waitForResults(URLS.length);
    }

    public void testLogs() throws Exception {
        //添加搜索
        executeSearches();
        //测试是否超时
        waitForResults();
        verifyLogs();
    }

    //添加搜索
    private void executeSearches() throws Exception {
        for (String url : URLS) {
            server.add(new Search(url, "xxx"));
        }
    }

    //测试是否超时
    private void waitForResults(int count) {
        //开始搜索时间
        long start = System.currentTimeMillis();
        //循环判断已经搜索次数是否比全部搜索次数小
        while (numberOfResults < count) {
            try {
                Thread.sleep(1);
            } catch (InterruptedException e) {
            }
            if (System.currentTimeMillis() - start > TIMEOUT) {
                fail("timeout");
            }
        }
    }

    //检测日志
    private void verifyLogs() {
        List<String> list = server.getLog();
        assertEquals(URLS.length * 2, list.size());
        for (int i = 0; i < URLS.length; i += 2) {
            verifySameSearch(list.get(i), list.get(i + 1));
        }
    }

    //断言日志内容
    private void verifySameSearch(String startSearchMsg, String endSearchMsg) {
        String startSearch = substring(startSearchMsg, Server.START_MSG);
        String endSearch = substring(endSearchMsg, Server.END_MSG);
        assertEquals(startSearch, endSearch);
    }


    private String substring(String string, String upTo) {
        int endInde = string.indexOf(upTo);
        assertTrue("didn't find " + upTo + " in " + string, endInde != -1);
        return string.substring(0, endInde);
    }
}
